# -*- coding: utf-8 -*-
# created on 2017/02/28

from __future__ import division
from sympy import sympify, Interval, S, Eq
from mathsolver.functions.base import BaseBelong, BaseFunction, BaseNumber, BaseFunc, BaseFuncEq
from mathsolver.functions.hanshu.helper import check_inter, check_func, check_eq, check_jiou
from mathsolver.functions.hanshu.jiaodian_geshu import JiaoDianGeShu
from mathsolver.functions.hanshu.zhouqi import HanShuZhouQi
from mathsolver.functions.hanshu.hanshu_inference import infer_zhouqi
from mathsolver.functions.hanshu.jiou_qiujiexishi import JiOuJieXiShi
from mathsolver.functions.hanshu.zhonghe_qiuzhi import is_jiou_dingyishi


def _get_jiaodian_geshu(zt, func, inter, eq, inter2):
    """求函数 eq 与 周期函数 (T, func, inter) 在区间 inter2 上交点个数"""
    # 已知函数在区间的表达式
    left, right, left_open, right_open = inter.args
    # f(x) = g(x-nT)
    n = sympify('n')
    fx_n = func.expression.subs(func.var, func.var - n * zt)
    geshu = 0

    # 往前后推10个周期
    for i in range(-10, 10):
        fx = fx_n.subs(n, i)
        x = Interval(left + i * zt, right + i * zt, left_open, right_open)
        x_intersect_inter2 = x.intersect(inter2)

        if isinstance(x_intersect_inter2, Interval):
            # 计算 fx 与 eq 在区间 x 上的交点个数
            jiaodian_n = JiaoDianGeShu().solver(
                BaseFunc({'var': 'x', 'expression': fx, 'type': '', 'name': 'f'}),
                eq,
                x_intersect_inter2).output[0].value
            geshu += jiaodian_n
    return geshu


class ZhouQiJiaoDianGeShu001(BaseFunction):
    """070.求与周期函数交点个数 - 类型一：给定周期 T"""

    def solver(self, *args):
        # 如果输入为周期
        if isinstance(args[0], BaseNumber):
            zt = sympify(args[0].value)
        # 如果输入为等式，则通过等式计算出周期
        elif isinstance(args[0], BaseFuncEq):
            zt = HanShuZhouQi().solver(args[0]).output[0].value
        elif isinstance(args[0], Eq):
            zt = HanShuZhouQi().solver(BaseFuncEq(args[0].args)).output[0].value
        else:
            raise ValueError('unknow input type %s' % type(args[0]))

        inter1, func, eq = args[1].interval, check_func(args[2]), check_eq(args[4])

        if args[3] is None:
            inter2 = S.Reals
        else:
            inter2 = check_inter(args[3])

        geshu = _get_jiaodian_geshu(zt, func, inter1, eq, inter2)
        self.output.append(BaseNumber(geshu))

        return self


class ZhouQiJiaoDianGeShu002(BaseFunction):
    """070.求与周期函数交点个数
    - 类型二：函数对称性推导周期
    - 类型三：根据奇偶性求出对称区间解析式
    题目给定区间 span 为半周期"""

    def solver(self, *args):
        # 处理输入
        eqs, belong, func, inter2, eq = args
        inter = belong.interval

        # 计算奇偶性
        for item_eq in eqs:
            if is_jiou_dingyishi(item_eq):
                jiou = check_jiou(item_eq)

        # 调用 duicheng_infer_zhouqi(Eq, Eq)，计算出 T
        zt, _steps = infer_zhouqi(*eqs)

        # 判断给定区间 inter 的 span 是否是半周期 T/2
        span_inter = inter.end - inter.start

        # 如果不是：调用 zhouqi_jiaodian_geshu_001
        if span_inter == zt:
            return ZhouQiJiaoDianGeShu001().solver(BaseNumber(zt), *args[1:])

        # 如果是：调用 jiou_jiexishi 输出 baseValue([[expr, D], [res, D1]])
        else:
            jiou_solver = JiOuJieXiShi().solver(jiou, inter, func)
            (func1, D1), (func2, D2) = jiou_solver.output[0].expression

            # 对 [func1, D1] 和 [func2, D2] 分别调用 zhouqi_jiaodian_geshu_001  把交点个数相加
            geshu1 = ZhouQiJiaoDianGeShu001().solver(
                BaseNumber(zt), BaseBelong(['x', "\\in", D1]),
                BaseFunc({'var': 'x', 'expression': func1, 'type': '', 'name': 'f'}),
                inter2, eq).output[0].sympify()

            geshu2 = ZhouQiJiaoDianGeShu001().solver(
                BaseNumber(zt), BaseBelong(['x', "\\in", D2]),
                BaseFunc({'var': 'x', 'expression': func2, 'type': '', 'name': 'f'}),
                inter2, eq).output[0].sympify()

        res = geshu1 + geshu2
        self.output.append(BaseNumber(res))
        return self


class ZhouQiJiaoDianGeShu(BaseFunction):
    """求与周期函数交点个数 - 类型 一、二、三"""

    def solver(self, *args):
        if isinstance(args[0], list):
            return ZhouQiJiaoDianGeShu002().solver(*args)
        else:
            return ZhouQiJiaoDianGeShu001().solver(*args)


if __name__ == '__main__':
    pass
